﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Xml;
using Douban.Api.Authorization;
using Douban.Api.Mail;
using Douban.Api.Web;
using Microsoft.Practices.Unity;

namespace Douban.Api.Infrastructure
{
    public class DoubanContext
    {
        public DoubanService MainService { get; set; }

        public IUnityContainer Container { get; set; }

        public AuthorizedResponse SendResource(string url, string resource, HttpMethods httpMethod)
        {
            AuthorizedRequest request = BuildRequest(url, 0, 0, true, httpMethod, resource);

            WebChannel channel = new WebChannel();
            return channel.Send(request);
        }

        public AuthorizedResponse GetProtectedResource(string url)
        {
            AuthorizedRequest request = BuildRequest(url, 0, 0);

            WebChannel channel = new WebChannel();

            return channel.Send(request);
        }

        public T GetProtectedResource<T>(string url) where T : Element, new()
        {
            return GetProtectedResource<T>(url, 0, 0);
        }

        public T GetProtectedResource<T>(string url, int startIndex, int maxResults) where T : Element, new()
        {
            AuthorizedRequest request = BuildRequest(url, startIndex, maxResults);

            WebChannel channel = new WebChannel();

            AuthorizedResponse response = channel.Send(request);

            T resource = InitializeObject<T>(response.Data);

            response.Close();

            return resource;
        }

        public T GetResource<T>(string url) where T : Element, new()
        {
            return GetResource<T>(url, 1, 50);
        }

        public T GetResource<T>(string url, int startIndex, int maxResults) where T : Element, new()
        {
            AuthorizedRequest request = BuildRequest(url, startIndex, maxResults, false);

            WebChannel channel = new WebChannel();

            AuthorizedResponse response = channel.Send(request);

            T resource = InitializeObject<T>(response.Data);

            response.Close();

            return resource;
        }

        private AuthorizedRequest BuildRequest(string url, int startIndex, int maxResults, 
            bool isProtected = true, HttpMethods method = HttpMethods.Get, string data = null)
        {
            var tokenPair = Container.Resolve<IAccessTokenManager>().GetToken();

            AuthorizedRequest request = new AuthorizedRequest();
            request.ConsumerKey = DoubanService.ConsumerKey;

            if (isProtected)
            {
                request.ConsumerSecret = DoubanService.ConsumerSecret;
                request.AccessToken = tokenPair.Key;
                request.AccessTokenSecret = tokenPair.Value;
            }

            request.StartIndex = startIndex;
            request.MaxResults = maxResults;
            request.RequestUri = new Uri(url);
            request.HttpMethod = method;
            
            if(!string.IsNullOrEmpty(data))
                request.Data = data;

            return request;
        }

        private T InitializeObject<T>(string returnData) where T : Element, new()
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(returnData);

            T resource = new T();
            resource.Initialize(doc.DocumentElement);
            resource.Resolve();

            return resource;
        }
    }
}
